/*
 * =============================================================================
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <eirikb@google.com> wrote this file. As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return Eirik Brandtzæg
 * =============================================================================
 */
package no.eirikb.roboco.terminal.element;

import java.io.IOException;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import no.eirikb.roboco.telnet.TelnetCommands;
import no.eirikb.roboco.terminal.Terminal;
import no.eirikb.roboco.terminal.command.Command;

/**
 *
 * @author eirikb
 * @author <a href="mailto:eirikb@google.com">eirikb@google.com</a>
 */
public abstract class CommandElement extends Element {

    private String readLine;
    private boolean echo;
    private boolean showPrompt;
    private boolean esc;

    public CommandElement(Terminal terminal, int x, int y, StringTokenizer st) {
        super(terminal, x, y, st);
        echo = true;
        showPrompt = true;
        readLine = "";
    }

    @Override
    public void init() {
        prompt();
    }

    @Override
    public void read(int c) {
        if (esc) {
            switch (c) {
                // LEFT
                case 68:
                //RIGHT
                case 67:
                    esc = false;
                    break;
                // UP
                case 65:
                    getTerminal().prevElement();
                    esc = false;
                    break;
                //DOWN
                case 66:
                    getTerminal().nextElement();
                    esc = false;
                    break;
            }
        } else {
            switch (c) {
                case 0:
                    break;
                case 4:
                    readLine = "exit";
                case 13:
                    if (readLine.length() > 0) {
                        readLine(readLine);
                    }
                    readLine = "";
                    break;
                case 27:
                    esc = true;
                    break;
                case 127:
                    if (readLine.length() > 0) {
                        readLine = readLine.substring(0, readLine.length() - 1);
                        getTerminal().getServer().echo(8);
                        getTerminal().getServer().sendText(TelnetCommands.CLEARCHARS(1));
                    }
                    break;
                default:
                    readLine += (char) c;
                    getTerminal().getServer().echo(c);
                    break;
            }
        }
    }

    public void setShowPrompt(boolean showPrompt) {
        this.showPrompt = showPrompt;
    }

    public void readLine(String line) {
        StringTokenizer st = new StringTokenizer(line, " ");
        String cmd = st.nextToken().trim();
        Command c = getCommand(cmd, st);
        if (c != null) {
            c.execute();
        } else {
            sendLine("UNKNOWN COMMAND: " + cmd);
        }
        prompt();
    }

    public Command getCommand(String cmd, StringTokenizer st) {
        try {
            String pkg = "no.eirikb.roboco.terminal.command.";
            Class cl = Class.forName(pkg + cmd.toUpperCase());
            java.lang.reflect.Constructor constructor = cl.getConstructor(new Class[]{Element.class, StringTokenizer.class});
            Command c = (Command) constructor.newInstance(this, st);
            return c;
        } catch (Exception ex) {
            Logger.getLogger(CommandElement.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public void prompt() {
        if (showPrompt) {
            sendLine("> ");
        }
    }

    public String getReadLine() {
        return readLine;
    }

    public void setReadLine(String readLine) {
        this.readLine = readLine;
    }

    public boolean isEcho() {
        return echo;
    }
}
